<?php
/**
 * Copyright (c) 2006, PORTALIER Julien
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @package      Feather PHP
 * @subpackage   Database
 * @copyright    Copyright (c) 2006, Julien PORTALIER
 * @link         http://feather.portalier.com
 * @license      http://www.opensource.org/licenses/mit-license.php The MIT License
 */

class db_mysql extends db_base
{
	protected $operators = '=|>|<|<=|>=|<>|<=>|like|regexp';
	
	// ignition
	
	protected function __start()
	{
		$connect = empty($this->conf['permanent']) ? 'mysql_connect' : 'mysql_pconnect';
		$this->link = $connect($this->conf['host'], $this->conf['login'], $this->conf['password']) or $this->error();
		mysql_select_db($this->conf['database'], $this->link) or $this->error();
		
		// unicode?
		if ($this->conf['unicode'])
			$this->execute("SET NAMES 'UTF8'");
	}
	
	function __stop()
	{
		mysql_close($this->link);
		$this->link = false;
	}
	
	// SQL
	
	function transactions($com, $v=null)
	{
		switch($com)
		{
			case 'start':
				return $this->execute('START TRANSACTION ;');
			case 'commit':
				return $this->execute('COMMIT ;');
			case 'rollback':
				return $this->execute('ROLLBACK ;');
			case 'autocommit':
				$v = $v ? 1 : 0;
				return $this->execute("SET AUTOCOMMIT = $v ;");
		}
	}
	
	function execute($sql)
	{
		if (!$this->link) $this->__start();
		$rs = mysql_query($sql, $this->link);
		if (DEBUG > 1) $this->debug($sql);
		return $rs;
	}
	
	function & query($sql, $process=Q_PROCESS_FULL, $tableName=0)
	{
		$data = array();
		$rs = $this->execute($sql);
		if ($rs and mysql_num_rows($rs) > 0)
		{
			switch($process)
			{
				case Q_PROCESS_FULL:
					// data[table][field] = value
					while ($row = mysql_fetch_row($rs))
					{
						$r = array();
						foreach ($row as $idx => $v)
						{
							$table = mysql_field_table($rs, $idx);
							if (empty($table)) $table = $tableName;
							$r[$table][mysql_field_name($rs, $idx)] = $v;
						}
						array_push($data, $r);
					}
					break;
				
				case Q_PROCESS_LITE:
					// data[field] = value
					while ($row = mysql_fetch_assoc($rs))
						array_push($data, $row);
					break;
				
				case Q_PROCESS_LIST:
					// data[index] = value
					while ($row = mysql_fetch_row($rs))
						array_push($data, $row[0]);
					break;
				
				default:
					while ($row = mysql_fetch_row($rs))
						array_push($data, $row);
			}
			mysql_free_result($rs);
		}
		return $data;
	}
	
	function & listFields($table)
	{
		$fields = array();
		$rs = $this->execute("DESC $table ;");
		while ($f = mysql_fetch_row($rs))
		{
			$name = array_shift($f);
			$fields[$name] = array(
				'type' => array_shift($f),
#				'null' => (array_shift($f) == 'NO')  ? false : true,
#				'key'  => (array_shift($f) == 'PRI') ? true  : false,
			);
		}
		mysql_free_result($rs);
		return $fields;
	}
	
	// data
	
	function limit($limit, $page=1)
	{
		if ($page > 1)
			return "LIMIT ".(($page - 1) * $limit).", ".$limit;
		elseif ($limit)
			return "LIMIT $limit";
	}
	
	function field($f)
	{
		// do not process field?
		if (strpos($f, '-! ') === 0)
			return str_replace('-! ', '', $f);
		
		// operator
		if (stripos($f, 'DISTINCT') !== false)
		{
			$op = 'DISTINCT';
			$f = str_ireplace('DISTINCT', '', $f);
		}
		else {
			$op = '';
		}
		$f = trim($f);
		
		if (strpos($f, '.'))
		{
			// model.field type
			list($m, $f) = explode('.', $f);
			$f = ($f != '*') ? "`$m`.`$f`" : "`$m`.$f";
		}
		else {
			// simple field
			$f = ($f != '*') ? "`$f`" : $f;
		}
		
		return "$op $f";
	}
	
	function value($v)
	{
		if (!$this->link)
			$this->__start();
		
		if (strpos($v, '-! ') === 0)
		{
			// do not process value
			return str_replace('-! ', '', $v);
		}
		elseif ($v === true)
			return 1;
		elseif ($v === false)
			return 0;
		elseif (!is_numeric($v))
		{
			// string
			if (empty($v))
				return 'NULL';
#			$v = str_replace(CRLF, LF, $v);
			$v = mysql_real_escape_string($v, $this->link);
			return "'$v'";
		}
		
		return $v;
	}
	
	function getLastInsertId()
	{
		return mysql_insert_id();
	}
	
	// debug
	
	protected function error($sql=null)
	{
		if (!is_null($sql)) debug($sql);
		die("MySQL error ".mysql_errno().": ".mysql_error());
	}
	
	protected function debug($sql)
	{
		$q = array(
			'sql'      => $sql,
			'error'    => mysql_errno($this->link)." ".mysql_error($this->link),
			'affected' => mysql_affected_rows($this->link)
		);
		array_push($this->debugs, $q);
	}
	
	function __destruct()
	{
		if (DEBUG < 2) return;
		echo '<table class="DBDebug" summary="'._('SQL queries for this page').'">' .
			'<tr>' .
			'<th>queries ( '.count($this->debugs).' )</th>' .
			'<th>error</th>' .
			'<th>affected</th>' .
			'</tr>';
		foreach($this->debugs as $d)
		{
			echo "\n<tr>" .
				"<td>{$d['sql']}</td>" .
				"<td>{$d['error']}</td>" .
				"<td>{$d['affected']}</td>" .
				"</tr>";
		}
		echo '</table>';
	}
}
?>